using System;
using System.Collections;
using System.Data;
using System.Data.SqlTypes;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.Purchasing.Enumerations;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;
using Constants=PHSRAG.Insight21.InsightUtilities.Constants;
using ExpenseConstants = PHSRAG.Insight21.Agreements.AgreementConstants.ExpenseInfoConstants;
using Helper=PHSRAG.WebControls.Helper;
using PurchasingEnums = PHSRAG.Insight21.Purchasing.Enumerations;

namespace PHSRAG.Insight21.Agreements
{
    /// <summary>
    /// The ExpenseOverview page provides the user with both the expense overview
    /// and expense details data depending on the data in the Agreement Details cache.
    /// In addition to the html output the page helps the user to download the report into
    /// excel or pdf output and in the case of expense details it helps the user to send the
    /// report by email.
    /// </summary>
    /// <remarks>
    /// The ExpenseOverview page supports searching/filtering the expense data
    /// based on user-defined and user-selectable search criteria.
    /// Following is the list of such criteria for expense overview/detail:
    /// <list type="bullet">
    /// <item><description>Category (select from a drop-down list)</description></item>
    /// <item><description>Account (select from a drop-down list)</description></item>
    /// <item><description>Expense Month From (calendar control)</description></item>
    /// <item><description>Expense Month To (calendar control)</description></item>	
    /// </list>	
    /// </remarks>
    public partial class AgreementsExpenseOverview : NoCachePage
    {
        #region Constants

        private const string CategoryColName = "CategoryID";
        private const int CategoryColumnIndex = 3;
        private const int CategoryIDColumnIndex = 1;
        private const string CurrentPageIndexKey = "currentPageIndexKey_aee2bc5e-01ba-4779-b7d5-f3bbab7a3761";
        private const string DefaultAmount = "0";
        private const string DefaultDropDownSelect = "-- Select --";
        private const string ExcelReportControlFilePath = "../../Agreements/Reports/ExpenseOverviewExcel.ascx";
        private const string ExpandedTag = "--Expanded--";
        private const string ExpandRowCommand = "ExpandRow";
        private const int FirstColumnIndex = 0;
        private const int FirstRowIndex = 0;
        private const int FixedColumnsCount = 4;
        private const string FundNumberKey = "fundNumberKey_aee2bc5e-01ba-4779-b7d5-f3bbab7a3761";
        private const string IsDetailsFlagKey = "isDetails_aee2bc5e-01ba-4779-b7d5-f3bbab7a3761";
        private const int MaxExpenseMonthColumns = 12;
        private const string MonthEndingDateKey = "monthEndingDateKey_aee2bc5e-01ba-4779-b7d5-f3bbab7a3761";
        private const string MonthStartingDateKey = "monthStartingDateKey_aee2bc5e-01ba-4779-b7d5-f3bbab7a3761";
        private const string NoOfExpenseMonthColumnsKey = "noOfExpenseMonthColumnsKey_aee2bc5e-01ba-4779-b7d5-f3bbab7a3761";
        private const string SearchCriteriaVersionKey = "searchCriteriaVersionKey_aee2bc5e-01ba-4779-b7d5-f3bbab7a3761";
        private const string StateColName = "StateColumn";

        #endregion

        #region Enumerations

        // Needs to be in sync with category id of the
        // eponymous categories in the database.
        private enum Category
        {
            FringeBenefits = 8,
            PatientCareDetails = 16,
            SalariesAndWages = 17
        }

        #endregion

        #region Instance Variables (Private)

        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;
        private ViewStateCachePolicy viewStateCachePolicy;

        #endregion

        #region Private properties

        /// <summary>
        /// Get the ExpenseOverview instance with its data loaded
        /// Check the cache if it already contains an instance of ExpenseOverview
        /// If the cache does not contain an instance of ExpenseOverview or if the
        /// searchCriteria version has changed load a new instance of expenseOverview
        /// with the active search criteria. Caches and returns the newly instantiated object.
        /// </summary>
        private ExpenseOverview ExpenseOverview
        {
            get
            {
                bool overviewLoaded = false;
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);

                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());


                ExpenseOverview expenseOverview = ResultsCache.GetObject(cachePolicy, ExpenseOverview.CacheKey) as ExpenseOverview;
                if ((expenseOverview == null) || (searchCriteria.Version != SearchCriteriaVersion))
                {
                    ResultsCache.PurgeObject(cachePolicy);

                    if (expenseOverview == null)
                    {
                        expenseOverview = new ExpenseOverview(cachePolicy);
                    }
                    else
                    {
                        cachePolicy.UnCache(ExpenseOverview.CacheKey);
                    }

                    searchContext.SetAdditionalSearchCriteria(Page.Request.Url.ToString(), Constants.GLPostAsOfDateKey, refreshDates.GLPostAsOfDate.ToShortDateString());

                    searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                    // needs to update the page's cache version number because the criteria has been added and version number
                    // of the search criteria has changed.
                    SearchCriteriaVersion = searchCriteria.Version;

                    expenseOverview.Load(DataAccess.ConnectionString, searchCriteria, Session.SessionID);
                    ResultsCache.SetObject(cachePolicy, ExpenseOverview.CacheKey, expenseOverview);
                    overviewLoaded = true;
                }
                if (overviewLoaded || !IsPostBack)
                {
                    OverviewSearch overviewSearch = (OverviewSearch) commonSearch.EmbeddedSearchControl;
                    string selectedCategory = Request.Form[overviewSearch.GetDDLID(OverviewSearch.DDL.Categories)];

                    DataTable distinctCategories = DataAccess.SelectDistinct(
                        expenseOverview.GetDataContainer().Tables[Constants.AgreementsConstants.CategoryTableName],
                        "CategoryID",
                        true);
                    DataTable categories = distinctCategories.Clone();
                    foreach (DataRow row in distinctCategories.Select("", "SortOrder"))
                    {
                        categories.ImportRow(row);
                    }
                    overviewSearch.SetDDLData(
                        (int) OverviewSearch.DDL.Categories,
                        categories,
                        "CategoryName",
                        "CategoryID",
                        selectedCategory);

                    if (selectedCategory != null)
                    {
                        if (String.Compare(selectedCategory, DefaultDropDownSelect) == 0)
                        {
                            selectedCategory = null;
                        }
                    }

                    if (!string.IsNullOrEmpty(selectedCategory))
                    {
                        DataTable distinctAccounts = DataAccess.SelectDistinct(
                            expenseOverview.GetDataContainer().Tables[Constants.AgreementsConstants.AccountsTableName],
                            "AccountID",
                            true);

                        DataTable filteredAccounts = distinctAccounts.Clone();
                        foreach (DataRow row in distinctAccounts.Select(
                            string.Format("CategoryID = {0}", selectedCategory), "AccountNumber"))
                        {
                            filteredAccounts.ImportRow(row);
                        }

                        filteredAccounts.Columns.Remove("AccountID");
                        filteredAccounts.Columns.Add("AccountID");
                        foreach (DataRow row in filteredAccounts.Rows)
                        {
                            row["AccountID"] = row["AccountNumber"].ToString().Substring(0, 6);
                        }

                        string selectedAccount = Request.Form[overviewSearch.GetDDLID(OverviewSearch.DDL.AccountNumbers)];
                        overviewSearch.SetDDLData(
                            (int) OverviewSearch.DDL.AccountNumbers,
                            filteredAccounts,
                            "AccountNumber",
                            "AccountID",
                            selectedAccount);
                    }
                    else
                    {
                        overviewSearch.SetDDLData(
                            (int) OverviewSearch.DDL.AccountNumbers, new DataTable(), string.Empty, string.Empty, string.Empty);
                    }
                }
                return expenseOverview;
            }
        }

        /// <summary>
        /// Get the ExpenseDetails instance with its data loaded
        /// Check the cache if it already contains an instance of ExpenseDetails
        /// If the cache does not contain an instance of ExpenseDetails or if the
        /// searchCriteria version has changed load a new instance of expenseDetails
        /// with the active search criteria. Caches and returns the newly instantiated object.
        /// </summary>
        private ExpenseDetails ExpenseDetails
        {
            get
            {
                bool detailsLoaded = false;
                SearchCriteria searchCriteria =
                    ((CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString());
                int searchVersion = searchCriteria.Version;

                ExpenseDetails expenseDetails = ResultsCache.GetObject(cachePolicy, ExpenseDetails.CacheKey) as ExpenseDetails;
                if ((expenseDetails == null) || (searchVersion != SearchCriteriaVersion))
                {
                    ResultsCache.PurgeObject(cachePolicy);
                    SearchCriteriaVersion = searchVersion;

                    if (expenseDetails == null)
                    {
                        expenseDetails = new ExpenseDetails(cachePolicy);
                    }
                    else
                    {
                        cachePolicy.UnCache(ExpenseDetails.CacheKey);
                    }

                    expenseDetails.Load(DataAccess.ConnectionString, searchCriteria, FundNumber, Session.SessionID);
                    ResultsCache.SetObject(cachePolicy, ExpenseDetails.CacheKey, expenseDetails);
                    detailsLoaded = true;
                }
                if (detailsLoaded || !IsPostBack)
                {
                    OverviewSearch overviewSearch = (OverviewSearch) commonSearch.EmbeddedSearchControl;

                    string selectedCategory = Request.Form[overviewSearch.GetDDLID(OverviewSearch.DDL.Categories)];
                    DataTable distinctCategories = DataAccess.SelectDistinct(
                        expenseDetails.GetDataContainer().Tables[Constants.AgreementsConstants.CategoryTableName],
                        "CategoryID",
                        true);
                    DataTable categories = distinctCategories.Clone();
                    foreach (DataRow row in distinctCategories.Select("", "SortOrder"))
                    {
                        categories.ImportRow(row);
                    }
                    overviewSearch.SetDDLData(
                        (int) OverviewSearch.DDL.Categories,
                        categories,
                        "CategoryName",
                        "CategoryID",
                        selectedCategory);

                    if (selectedCategory != null)
                    {
                        if (String.Compare(selectedCategory, DefaultDropDownSelect) == 0)
                        {
                            selectedCategory = null;
                        }
                    }

                    if (!string.IsNullOrEmpty(selectedCategory))
                    {
                        DataTable distinctAccounts = DataAccess.SelectDistinct(
                            expenseDetails.GetDataContainer().Tables[Constants.AgreementsConstants.AccountsTableName],
                            "AccountID",
                            true);

                        DataTable filteredAccounts = distinctAccounts.Clone();
                        foreach (DataRow row in distinctAccounts.Select(
                            string.Format("CategoryID = {0}", selectedCategory), "AccountNumber"))
                        {
                            filteredAccounts.ImportRow(row);
                        }

                        filteredAccounts.Columns.Remove("AccountID");
                        filteredAccounts.Columns.Add("AccountID");
                        foreach (DataRow row in filteredAccounts.Rows)
                        {
                            row["AccountID"] = row["AccountNumber"].ToString().Substring(0, 6);
                        }

                        string selectedAccount = Request.Form[overviewSearch.GetDDLID(OverviewSearch.DDL.AccountNumbers)];
                        overviewSearch.SetDDLData(
                            (int) OverviewSearch.DDL.AccountNumbers,
                            filteredAccounts,
                            "AccountNumber",
                            "AccountID",
                            selectedAccount);
                    }
                    else
                    {
                        overviewSearch.SetDDLData(
                            (int) OverviewSearch.DDL.AccountNumbers, new DataTable(), string.Empty, string.Empty, string.Empty);
                    }
                }
                return expenseDetails;
            }
        }

        /// <summary>
        /// Get and Set the search criteria version
        /// </summary>
        private int SearchCriteriaVersion
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable;
                return (h == null || h[SearchCriteriaVersionKey] == null) ? 0 : (int) h[SearchCriteriaVersionKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable ?? new Hashtable();
                h[SearchCriteriaVersionKey] = value;
                pageCachePolicy.Cache(Keys.ExpenseInfoPageKey, h);
            }
        }

        /// <summary>
        /// Get and Set the month ending date used for the ExpenseDetails load
        /// </summary>
        private string MonthEndingDate
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable;
                return (h == null || h[MonthEndingDateKey] == null) ? DateTime.Now.ToShortDateString() : (string) h[MonthEndingDateKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable ?? new Hashtable();

                if (h.ContainsKey(MonthEndingDateKey) && ((string) h[MonthEndingDateKey] != value))
                {
                    cachePolicy.UnCache(ExpenseDetails.CacheKey);
                }

                h[MonthEndingDateKey] = value;
                pageCachePolicy.Cache(Keys.ExpenseInfoPageKey, h);
            }
        }

        /// <summary>
        /// Get and Set the month starting date used for the ExpenseDetails load
        /// </summary>
        private string MonthStartingDate
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable;
                return (h == null || h[MonthStartingDateKey] == null) ? DateTime.Now.ToShortDateString() : (string) h[MonthStartingDateKey];
            }

            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable ?? new Hashtable();

                if (h.ContainsKey(MonthStartingDateKey) && ((string) h[MonthStartingDateKey] != value))
                {
                    cachePolicy.UnCache(ExpenseDetails.CacheKey);
                }

                h[MonthStartingDateKey] = value;
                pageCachePolicy.Cache(Keys.ExpenseInfoPageKey, h);
            }
        }

        /// <summary>
        /// Get and Set the fund number which is used to load the ExpenseDetails data
        /// </summary>
        private string FundNumber
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable;
                return (h == null || h[Keys.FundNumberKey] == null) ? string.Empty : (string) h[Keys.FundNumberKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable ?? new Hashtable();

                if (h.ContainsKey(Keys.FundNumberKey) && ((string) h[Keys.FundNumberKey] != value))
                {
                    cachePolicy.UnCache(ExpenseDetails.CacheKey);
                }

                h[Keys.FundNumberKey] = value;
                pageCachePolicy.Cache(Keys.ExpenseInfoPageKey, h);
            }
        }

        /// <summary>
        /// Get the flag which specifies the context of the page (Overview/Details)
        /// </summary>
        private bool IsDetail
        {
            get { return FundNumber != string.Empty; }
        }

        /// <summary>
        /// Get and Set the index of the current page. Using the value for the current page index,
        /// the expense month columns to be displayed on this page is decided.
        /// </summary>
        private int CurrentPageIndex
        {
            get
            {
                object o = viewStateCachePolicy.GetCachedObject(CurrentPageIndexKey);
                return (o == null) ? 0 : (int) o;
            }
            set { viewStateCachePolicy.Cache(CurrentPageIndexKey, value); }
        }

        /// <summary>
        /// Get and Set the current value for Number of expense month columns to display on
        /// the current page.
        /// </summary>
        private int ExpenseMonthColumnCount
        {
            get
            {
                object o = viewStateCachePolicy.GetCachedObject(NoOfExpenseMonthColumnsKey);
                return (o == null) ? 0 : (int) o;
            }
            set { viewStateCachePolicy.Cache(NoOfExpenseMonthColumnsKey, value); }
        }

        /// <summary>
        /// Get and Set the dataset containing the data for the current page.
        /// </summary>
        private DataSet ActiveData
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable;
                return (h == null || h[ExpenseConstants.ActiveDataKey] == null) ? null : (DataSet) h[ExpenseConstants.ActiveDataKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable ?? new Hashtable();
                h[ExpenseConstants.ActiveDataKey] = value;
                pageCachePolicy.Cache(Keys.ExpenseInfoPageKey, h);
            }
        }

        /// <summary>
        /// Get the datacontainer from the expense overview/detail instance, based on the
        /// context of the page(Overview/Detail).
        /// </summary>
        private DataSet ExpenseDataContainer
        {
            get { return IsDetail ? ExpenseDetails.GetDataContainer() : ExpenseOverview.GetDataContainer(); }
        }

        #endregion

        #region Event handlers

        #region Page Load

        /// <summary>
        ///  Handler for the event raised when the page is being loaded.
        ///  Identify the context in which the page is being loaded (Overview or Details)
        ///  and load the appropriate controls and data on the page
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            /* ys985 - 01/30/2008
             * Set SQLReportName property to the name of the report on the report server
             */
            reportDownload.SQLReportName = "expensereport";

            System.Diagnostics.Trace.WriteLine(string.Format("{0}: {1}", DateTime.Now, postbackGuard.IsValid));
            if (!postbackGuard.IsValid)
            {
                return;
            }

            try
            {
                annunciator.Message = string.Empty;
                annunciator.Title = string.Empty;

                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);

                Hashtable incomingHashTable = pageCachePolicy.GetCachedObject(Constants.AgreementsConstants.AgreementDetailsKey) as Hashtable;

                if (!IsPostBack)
                {
                    if (incomingHashTable != null)
                    {
                        if ((incomingHashTable[Keys.FundNumberKey] == null) || (incomingHashTable[Keys.JournalEndDateKey] == null))
                        {
                            throw (new Exception("Expense Details requires fund number and month ending Date"));
                        }

                        SearchCriteria commonSearchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                        searchContext.ClearAdditionalSearchCriteria(Constants.FundIDKey);

                        FundNumber = incomingHashTable[Keys.FundNumberKey].ToString();

                        string startDate = (incomingHashTable[Keys.JournalStartDateKey] != null) ?
                                                                                                     incomingHashTable[Keys.JournalStartDateKey].ToString() : string.Empty;
                        searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Detail,
                            Page.Request.Url.ToString(),
                            Constants.AllExpensesKey,
                            incomingHashTable[Keys.AllExpensesKey] as string,
                            PurchasingSearch.ExpenseStatusLabel, CommonSearch.LabelValueSeparator,
                            incomingHashTable[Keys.AllExpensesKey] as string);

                        if (commonSearchCriteria[Constants.ExpenseFromDateKey] == null)
                        {
                            searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Detail,
                                Page.Request.Url.ToString(),
                                Constants.ExpenseFromDateKey,
                                startDate == "1/1/1900" ? null : startDate,
                                PurchasingSearch.TransactionDateFromLabel, CommonSearch.LabelValueSeparator,
                                startDate == "1/1/1900" ? null : startDate);
                        }

                        if (commonSearchCriteria[Constants.ExpenseToDateKey] == null)
                        {
                            searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Detail,
                                Page.Request.Url.ToString(),
                                Constants.ExpenseToDateKey,
                                incomingHashTable[Keys.JournalEndDateKey].ToString(),
                                PurchasingSearch.TransactionDateToLabel, CommonSearch.LabelValueSeparator,
                                incomingHashTable[Keys.JournalEndDateKey].ToString());
                        }
                    }
                    else
                    {
                        FundNumber = string.Empty;
                    }
                }


                // The check for whether to operate in overview or detail mode CANNOT be done BEFORE the FundNumber property setter
                // is invoked since IsDetail uses the FundNumber property.
                breadCrumb.Add(IsDetail ? "Expense Details" : "Expense Overview",
                    Settings.GetKeyValue("SubNavigation.Agreements.ExpenseOverviewURL", string.Empty), 2);

                SetMode();

                if (IsPostBack)
                {
                    //reset the criteria for values that are passed into this page via links so they don't "stick"
                    searchContext.ClearAdditionalSearchCriteria(Constants.FundIDKey);

                    AddExpenseMonthColumns();
                    if (ActiveData.Tables[Constants.AgreementsConstants.CategoryTableName].Rows.Count > 0)
                    {
                        dataGrid.DataBind();
                    }
                    else
                    {
                        dataGrid.Visible = false;
                        pager.Visible = false;
                        annunciator.Message = "No expense info found for fund";
                    }
                }
                else
                {
                    if (IsDetail)
                    {
                        int budgetYear = (incomingHashTable[Keys.BudgetYearKey] == null) ? 0 : (int) incomingHashTable[Keys.BudgetYearKey];
                        projectHeaderBar.LoadProjectHeader(FundNumber, 0, budgetYear);
                        incomingHashTable[Keys.RefreshBudgetDetailDataKey] = true;
                        pageCachePolicy.Cache(Constants.AgreementsConstants.AgreementDetailsKey, incomingHashTable);
                        agreementDetailsSubNavigation.SelectedLink = AgreementDetailsSubNavigation.ExpenseDetailCommand;
                    }
                    else
                    {
                        agreementsSubNavigation.SelectedOverviewLink = AgreementsSubNavigation.ExpenseOverviewCommand;
                    }

                    //show the last page by default
                    int rowCount = ExpenseDataContainer.Tables[ExpenseConstants.FundsPerMonthTableName].Rows.Count;
                    if (rowCount > 0)
                    {
                        CurrentPageIndex = (rowCount/MaxExpenseMonthColumns) +
                            (((rowCount%MaxExpenseMonthColumns) == 0) ? 0 : 1) - 1;
                    }

                    LoadData();
                }
                refreshDates.GLAsOfDateVisible = true;
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred during page load";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #region Expense Info Expanding DataGrid Events

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is databound.
        /// Bind the approriate values to the different controls on the expanding datagrid and 
        /// the data grid footers. Removes the navigation links at the account(detailed) level.
        /// While binding data check if the amount field has negative values, if yes assign a 
        /// style for displaying negative values. This formatting  is applied to Item types,
        /// alternating Item types and the footer type.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            DataGridItem item = e.Item;
            int columnCount = ExpenseMonthColumnCount + FixedColumnsCount;
            if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
            {
                DataRowView row = (DataRowView) item.DataItem;

                //If it is the fringe category row then there is 
                //no need to link to labor distribution b/c we don't have enough the detailed data available
                int categoryId = Convert.ToInt32(row[CategoryColName].ToString());
                if (categoryId == (int) Category.FringeBenefits || categoryId == (int) Category.PatientCareDetails)
                {
                    //loop through the items columns beginning with the second one 
                    //since the first is reserved for the expanding grid icon
                    for (int i = 1; i < item.Cells.Count; i++)
                    {
                        TableCell amountCell = item.Cells[i];
                        if (amountCell.Controls.Count > 0 && amountCell.Controls[0] is LinkButton)
                        {
                            //get rid of the link and add a literal
                            string dataValue = ((LinkButton) amountCell.Controls[0]).Text;
                            amountCell.Controls.Clear();
                            amountCell.Controls.Add(new LiteralControl(dataValue));
                        }
                    }
                }

                FormatCurrencyValue(item.Cells[columnCount], row[ExpenseConstants.TotalExpenseAmountColumnName]);

                if (categoryId != (int) Category.FringeBenefits && categoryId != (int) Category.PatientCareDetails)
                {
                    if ((row[StateColName] != DBNull.Value && (string) row[StateColName] != ExpandedTag) ||
                        (Convert.ToInt32(row[CategoryColName].ToString()) == (int) Category.SalariesAndWages && !IsUserAuthorized((int) AccessRightBit.ViewSalaryInformation)))
                    {
                        item.CssClass =
                            (item.ItemType == ListItemType.Item) ? AgreementConstants.GridItemExpanded : AgreementConstants.GridAltItemExpanded;
                        for (int index = FixedColumnsCount; index < columnCount; ++index)
                        {
                            ConfigureNewLabel(item.Cells[index].Controls);
                        }
                    }
                }

                foreach (TableCell cell in e.Item.Cells)
                {
                    foreach (Control control in cell.Controls)
                    {
                        if (control is LinkButton)
                        {
                            ((LinkButton) control).Enabled = (((LinkButton) control).Text != Constants.ZeroDollarsNoCents);
                        }
                    }
                }
            }
            else if (item.ItemType == ListItemType.Footer)
            {
                item.Cells[CategoryColumnIndex].Controls.Add(GetCategoryFooterTable());
                item.Cells[columnCount].Controls.Add(GetTotalsFooterTable());
            }
        }

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is clicked upon.
        /// Redirect control to the page according to the business rules and according to the
        /// context of the page(Overview/Details)
        /// Cache the appropriate key depending on which page the control is being redirected.
        /// This event is processed only when the command name associated with the event is not
        /// expand row command. The expandRowCommand is for the expanding data grid.
        /// </summary>
        /// <remarks>
        /// The redirection is based on the following scenario:
        /// <list type="bullet">
        /// <item><description>BudgetOverview/Detail - CashBalanceLink</description></item>
        /// <item><description>RevenueBreakDown - RevenueLink</description></item>
        /// <item><description>TransactionsOverview/ Detail - For categories other than Salaries or Fringe Benefits.</description></item>
        /// <item><description>SalaryOverview/Details - For Salaries or Fringe Benefits categories</description></item> 
        /// </list>
        /// </remarks>
        /// <param name="source">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                if (e.CommandName != ExpandRowCommand)
                {
                    DataGridItem item = e.Item;
                    string navigationURL = string.Empty;
                    bool isDetail = IsDetail;
                    Hashtable dictionary = new Hashtable();
                    Hashtable detailsDictionary = isDetail ? (Hashtable) cachePolicy.GetCachedObject(Constants.AgreementsConstants.AgreementDetailsKey) : new Hashtable();

                    if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem ||
                        item.ItemType == ListItemType.Footer)
                    {
                        //get the month end date 
                        string[] dateParts = null;
                        if (e.CommandName == "RevenueLink")
                        {
                            //get the month end date from the header of the column clicked
                            LinkButton lb = e.CommandSource as LinkButton;
                            if (lb != null)
                            {
                                for (int i = 0; i < e.Item.Cells.Count; ++i)
                                {
                                    if (e.Item.Cells[i].Controls.Count > 0)
                                    {
                                        WebControl c = (WebControl) e.Item.Cells[i].Controls[0].Controls[3].Controls[0].Controls[0];
                                        if (c == lb)
                                        {
                                            dateParts =
                                                ((ExpenseTemplates.HeaderTemplate) ((TemplateColumn) dataGrid.Columns[i]).HeaderTemplate).HeaderText.Split('/');

                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            LinkButton button = e.CommandSource as LinkButton;
                            if (button == null)
                            {
                                throw new Exception("CommandSource is not a link button");
                            }
                            dateParts = button.CommandName.Split('/');
                        }

                        switch (e.CommandName)
                        {
                            case "CashBalanceLink":
                                navigationURL = Settings.GetKeyValue("SubNavigation.Agreements.BudgetOverviewURL", string.Empty);
                                break;

                            case "RevenueLink":
                                // the revenue amount clicked is not passed so that the breakdown page will
                                // display the actual total from its data even if it doesn't match this amount
                                if (isDetail)
                                {
                                    //detailsDictionary[Keys.RevenueTotalKey] = (Convert.ToDecimal(e.CommandArgument)).ToString("c");
                                    detailsDictionary[Keys.PageReferrerKey] = "ExpenseDetails";
                                    detailsDictionary[Keys.RevenueEndDateKey] = string.Format("{0}/{1}/{2}", dateParts[0], dateParts[1], dateParts[2]);
                                    detailsDictionary[Keys.RevenueStartDateKey] = string.Format("{0}/01/{1}", dateParts[0], dateParts[2]);
                                    detailsDictionary[Keys.FundNumberKey] = FundNumber;
                                    detailsDictionary[Keys.AccountNumberKey] = "&nbsp;";

                                    if (e.CommandArgument != null)
                                    {
                                        decimal total = Convert.ToDecimal(e.CommandArgument);
                                        string totalAmt = total.ToString("c");
                                        // remove the decimal point and cents
                                        detailsDictionary[Keys.RevenueTotalKey] = totalAmt.IndexOf("(") > -1 ? totalAmt.Remove(totalAmt.Length - 4, 4) : totalAmt.Remove(totalAmt.Length - 3, 3);
                                    }
                                    else
                                    {
                                        detailsDictionary[Keys.RevenueTotalKey] = string.Empty;
                                    }
                                }
                                else
                                {
                                    decimal total = Convert.ToDecimal(e.CommandArgument);
                                    string totalAmt = total.ToString("c");
                                    // remove the decimal point and cents
                                    dictionary[Keys.RevenueTotalKey] = totalAmt.IndexOf("(") > -1 ? totalAmt.Remove(totalAmt.Length - 4, 4) : totalAmt.Remove(totalAmt.Length - 3, 3);
                                    dictionary.Add(Keys.PageReferrerKey, "ExpenseOverview");
                                    dictionary.Add(Keys.RevenueEndDateKey, string.Format("{0}/{1}/{2}", dateParts[0], dateParts[1], dateParts[2]));
                                    dictionary.Add(Keys.RevenueStartDateKey, string.Format("{0}/01/{1}", dateParts[0], dateParts[2]));
                                    pageCachePolicy.Cache(Keys.AccountNumberKey, dictionary);
                                }

                                navigationURL = Settings.GetKeyValue("Other.Agreements.RevenueBreakdownURL", string.Empty);
                                break;

                            default:
                                int categoryID = Convert.ToInt32(item.Cells[CategoryIDColumnIndex].Text);
                                if (categoryID == (int) Category.SalariesAndWages || categoryID == (int) Category.FringeBenefits)
                                {
                                    dictionary.Add(Constants.PageNameKey, "Expense");
                                    dictionary.Add(Constants.CategoryIDKey, categoryID);
                                    dictionary.Add(Constants.PersonnelConstants.EndDateKey,
                                        string.Format("{0}/{1}/{2}", dateParts[0], dateParts[1], dateParts[2]));
                                    if (isDetail)
                                    {
                                        dictionary.Add(Constants.FundNumberKey, FundNumber);
                                    }
                                    dictionary.Add(Constants.AccountIDKey, Convert.ToInt32(((CommonSearchContext) cachePolicy.
                                        GetCachedObject(CommonSearchContext.CacheKey)).
                                        GetSearchCriteria(Page.Request.Url.ToString())[Constants.AccountNumberKey]));

                                    navigationURL = Settings.GetKeyValue("SubNavigation.Personnel.LaborDistributionURL", string.Empty);
                                }
                                else
                                {
                                    pageCachePolicy.Cache(Keys.SelectedLinkKey, e.CommandName);
                                    if (isDetail)
                                    {
                                        detailsDictionary[Keys.BudgetStartDateKey] = string.Format("{0}/01/{1}", dateParts[0], dateParts[2]);
                                        detailsDictionary[Keys.BudgetEndDateKey] = string.Format("{0}/{1}/{2}", dateParts[0], dateParts[1], dateParts[2]);
                                        detailsDictionary[Keys.CategoryIDKey] = categoryID;
                                        detailsDictionary[Keys.POAPEncumbranceKey] = false;
                                        detailsDictionary[Keys.TransactionDateTypeKey] = (int) TransactionDateType.VoucherAccountingLineDate; // voucher acct. line date
                                        navigationURL = Settings.GetKeyValue("SubNavigation.AgreementDetails.TransactionDetailsURL", string.Empty);
                                        if (categoryID == (int) Category.PatientCareDetails && IsUserAuthorized((int) AccessRightBit.ViewPatientCareDetails))
                                        {
                                            navigationURL = Settings.GetKeyValue("SubNavigation.AgreementDetails.PatientCareDetailsURL", string.Empty);
                                        }
                                    }
                                    else
                                    {
                                        dictionary.Add(Keys.BudgetStartDateKey, string.Format("{0}/01/{1}", dateParts[0], dateParts[2]));
                                        dictionary.Add(Keys.BudgetEndDateKey, string.Format("{0}/{1}/{2}", dateParts[0], dateParts[1], dateParts[2]));
                                        dictionary.Add(Keys.CategoryIDKey, categoryID);
                                        dictionary.Add(Keys.POAPEncumbranceKey, false);
                                        navigationURL = Settings.GetKeyValue("SubNavigation.Agreements.TransactionsOverviewURL", string.Empty);
                                    }
                                }
                                break;
                        }
                    }

                    if (dictionary.Count > 0)
                    {
                        pageCachePolicy.Cache(Keys.IncomingDataKey, dictionary);
                    }

                    if (detailsDictionary.Count > 0)
                    {
                        pageCachePolicy.Cache(Constants.AgreementsConstants.AgreementDetailsKey, detailsDictionary);
                    }

                    PurgeCache();
                    Response.Redirect(navigationURL, false);
                }
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while handling the selected item";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handles the event whenever a row is either expanded or collapsed.
        /// Identify the context of the page (Overview/Details) using the flag stored in the viewState
        /// Depending on the sortOrder pick the appropriate rows from the accounts table and return
        /// </summary>
        /// <param name="key">The sortOrder which is used as the key</param>
        /// <returns>This Method will return Expanded DataSet(Account level information)for display</returns>
        protected object OnItemExpanded(string key)
        {
            try
            {
                //Identify the category that was clicked to expand
                int clickedRowIndex = 0;
                for (int i = 0; i < dataGrid.Items.Count; ++i)
                {
                    if (dataGrid.Items[i].Cells[2].Text == key)
                    {
                        clickedRowIndex = i;
                        break;
                    }
                }

                int selectedCategoryID = Convert.ToInt32(dataGrid.Items[clickedRowIndex].Cells[1].Text);

                LoadActiveAccountDataTables(selectedCategoryID);

                DataTable childTable = ActiveData.Tables[Constants.AgreementsConstants.AccountsTableName];
                DataRow[] filteredChildRows = childTable.Select(string.Format("{0}={1}", AgreementConstants.SortOrderColName, key));
                DataTable filteredChildTable = childTable.Clone();

                foreach (DataRow row in filteredChildRows)
                {
                    filteredChildTable.ImportRow(row);
                }

                DataView dataView = new DataView(filteredChildTable);
                dataView.Sort = "CategoryName asc";

                filteredChildTable = dataView.Table.Clone();
                foreach (DataRowView dataRowView in dataView)
                {
                    filteredChildTable.ImportRow(dataRowView.Row);
                }

                return filteredChildTable;
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred during item expansion";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
            return null;
        }

        #endregion

        #region Navigate expense month columns

        /// <summary>
        /// Handler for the event raised when the FirstPage link in clicked in the Pager control.
        /// Set the current page index to 0, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnFirstPage(object sender, CommandEventArgs e)
        {
            try
            {
                CurrentPageIndex = 0;
                SetMode();
                LoadData();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while navigating to first page";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Fires when a link on the breadcrumb is clicked upon. 
        /// </summary>
        /// <param name="sender">The object that raised the event.</param>
        /// <param name="e">Information associated with the even itself.</param>
        protected void OnBreadCrumbNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                if (((CommandEventArgs) (e.CommandArgument)).CommandName == Convert.ToString((int) SearchCriteria.Level.Summary))
                {
                    //set the search context's level to the correct level
                    CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                    searchContext.CurrentLevel = SearchCriteria.Level.Summary;
                }
                PurgeCache();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while navigating to next page via breadcrumb";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the NextPage link in clicked in the Pager control.
        /// Increment the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnNextPage(object sender, CommandEventArgs e)
        {
            try
            {
                ++CurrentPageIndex;
                SetMode();
                LoadData();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while navigating to next page";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the PreviousPage link in clicked in the Pager control.
        /// Decrement the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnPreviousPage(object sender, CommandEventArgs e)
        {
            try
            {
                --CurrentPageIndex;
                SetMode();
                LoadData();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while navigating to previous page";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the LastPage link in clicked in the Pager control.
        /// Set the current page index to one less than the total page count (index is 0-based), bind the datagrid with
        /// data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnLastPage(object sender, CommandEventArgs e)
        {
            try
            {
                CurrentPageIndex = pager.PageCount - 1;
                SetMode();
                LoadData();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while navigating to last page";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #region Search

        /// <summary>
        /// Handler for the event raised when search is clicked on the search control
        /// It loads the data.
        /// </summary>
        /// <param name="args">Argument associated with the event (contains the search criteria dictionary)</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            try
            {
                annunciator.Title = string.Empty;
                annunciator.Message = string.Empty;

                CurrentPageIndex = 0;
                SetMode();
                LoadData();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while executing the search";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the "Clear Selection" button is clicked on thhe budget overview page
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            dataGrid.Visible = false;
            pager.Visible = false;
        }

        /// <summary>
        /// Handler for the event raised when the selected index changes
        /// on the overview search's category dropdown list control
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnCategoryChanged(object sender, CommandEventArgs e)
        {
            try
            {
                OverviewSearch overviewSearch = (OverviewSearch) commonSearch.EmbeddedSearchControl;

                int category = Convert.ToInt32(e.CommandArgument);

                if (category > 0)
                {
                    LoadActiveAccountDataTables(category);
                    DataTable distinctAccounts = DataAccess.SelectDistinct(
                        (IsDetail)
                            ? ExpenseDetails.GetDataContainer().Tables[Constants.AgreementsConstants.AccountsTableName]
                            : ExpenseOverview.GetDataContainer().Tables[Constants.AgreementsConstants.AccountsTableName],
                        "AccountID",
                        true);

                    DataTable filteredAccounts = distinctAccounts.Clone();
                    foreach (DataRow row in distinctAccounts.Select(
                        string.Format("CategoryID = {0}", category), "AccountNumber"))
                    {
                        filteredAccounts.ImportRow(row);
                    }

                    filteredAccounts.Columns.Remove("AccountID");
                    filteredAccounts.Columns.Add("AccountID");
                    foreach (DataRow row in filteredAccounts.Rows)
                    {
                        row["AccountID"] = row["AccountNumber"].ToString().Substring(0, 6);
                    }

                    overviewSearch.SetDDLData(
                        (int) OverviewSearch.DDL.AccountNumbers, filteredAccounts, "AccountNumber", "AccountID", string.Empty);
                }
                else
                {
                    overviewSearch.SetDDLData(
                        (int) OverviewSearch.DDL.AccountNumbers, new DataTable(), string.Empty, string.Empty, string.Empty);
                }
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while handling OnCatgegoryChanged";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #region Downloads

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            annunciator.Title = "Following error(s) occurred while downloading";
            annunciator.Message = ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
        }

        /// <summary>
        /// Handles Send By Email button clicks by preparing a MailMessage to send back to the 
        /// InsightDownloadBar control
        /// </summary>
        /// <remarks>
        /// This method generates the raw information needed for the InsightDownloadBar 
        /// to process and send an e-mail with a link back to the page with the correct 
        /// session settings.This page stores fund number and month ending data into the database.
        /// This page has no summary information, hence it passes an empty hashtable.
        /// </remarks>		
        ///<param name="webConfigURLKey">URL information to see the page</param>
        ///<param name="queryID">Last inserted value from the database</param>
        ///<param name="summaryInfo">Summary information to be sent</param>
        protected void OnSendByEmail(out string webConfigURLKey, out int queryID, out Hashtable summaryInfo)
        {
            try
            {
                webConfigURLKey = "SubNavigation.AgreementDetails.ExpenseDetailsURL";
                queryID = Projections.GetQueryId(string.Format("{0}={1}&{2}={3}", Keys.FundNumberKey, FundNumber,
                    Keys.JournalEndDateKey, MonthEndingDate));
                summaryInfo = null;
                SetMode();
                AddExpenseMonthColumns();
                dataGrid.DataBind();
            }
            catch (Exception ex)
            {
                webConfigURLKey = null;
                queryID = -1;
                summaryInfo = null;
                annunciator.Title = "Following error(s) occurred while sending email";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #region Tab Navigation event handlers

        /// <summary>
        /// Resets the subnavigation selected link before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                PurgeCache();
                agreementsSubNavigation.Reset();
                agreementDetailsSubNavigation.Reset();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while resetting navigation context";
                annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Fires when an overview/detail subnavigation control tab is clicked upon.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnSubNavNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        #endregion

        #endregion

        #region Private methods

        private bool IsUserAuthorized(int accessRight)
        {
            bool isPI = false;
            Hashtable h = cachePolicy.GetCachedObject(Constants.AgreementsConstants.AgreementDetailsKey) as Hashtable;
            // This page is used for overview and details, overview has no Details data in cache
            if (h == null)
            {
                return false;
            }
            if (accessRight == (int) AccessRightBit.ViewPatientCareDetails
                || accessRight == (int) AccessRightBit.ViewSalaryInformation)
            {
                UserContext context = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                int agreementId = Convert.ToInt32(h[Keys.AgreementIdKey]);
                Agreement agreement = new Agreement(cachePolicy);
                agreement.Load(DataAccess.ConnectionString, agreementId);
                isPI = (context.DomainUserId == agreement.PIID);
            }
            int accessRights = (h[Constants.AgreementsConstants.AccessRightsKey] != null) ? Convert.ToInt32(h[Constants.AgreementsConstants.AccessRightsKey]) : 0;
            return isPI || ((accessRights & accessRight) != 0);
        }

        /// <summary>
        /// Loads data for the current page in the active dataset, adds the required expense month 
        /// columns to the datagrid and loads data in the datagrid.
        /// </summary>
        private void LoadData()
        {
            LoadActiveDataTables();
            AddExpenseMonthColumns();
            LoadDataGrid();
        }

        /// <summary>
        /// Load the datagrid with data for display.
        /// The data is loaded from the data set having the active data for this page.
        /// </summary>
        private void LoadDataGrid()
        {
            if (ActiveData.Tables[Constants.AgreementsConstants.CategoryTableName].Rows.Count > 0)
            {
                dataGrid.DataSource = ActiveData.Tables[Constants.AgreementsConstants.CategoryTableName];
                dataGrid.DataBind();
                dataGrid.Visible = true;
                pager.Visible = true;
            }
            else
            {
                dataGrid.Visible = false;
                pager.Visible = false;
                annunciator.Message = "No expense info found for fund";
            }
        }

        /// <summary>
        /// Show/Hide controls depending on whether the page is in overview/detail mode.
        /// </summary>
        private void SetMode()
        {
            bool isDetail = IsDetail;
            agreementDetailsSubNavigation.Visible = projectHeaderBar.Visible = isDetail;
            agreementsSubNavigation.EnableOverviewNavigation = !isDetail;
            pageName.Text = (isDetail) ? "Expense Details" : "Expense Overview";
        }


        /// <summary>
        /// Constructs the active data tables and loads them with data. The data
        /// on the active tables is subset of data taken from the ExpenseOverview/Details
        /// instance. The subset is the data required for the current page. The data in the
        /// tables is row wise, which is transformed column wise at the run time based on the
        /// current page index. Only the data pertinent for the current set of expense months
        /// on this page is loaded from the original data container and loaded in repective tables
        /// in the ActiveData dataset, which is then used for binding data to data grid.
        /// </summary>
        private void LoadActiveAccountDataTables(int categoryID)
        {
            DataSet activeData = ActiveData;

            DataTable activeAccounts = activeData.Tables[Constants.AgreementsConstants.AccountsTableName];

            DataSet dataContainer = ExpenseDataContainer;
            DataTable accounts = dataContainer.Tables[Constants.AgreementsConstants.AccountsTableName];
            DataTable accountsTotal = dataContainer.Tables[ExpenseConstants.AccountTotalTableName];

            DataRow[] filteredAccountTotals = accountsTotal.Select(String.Format("CategoryID = {0}", categoryID));
            if (filteredAccountTotals.Length == 0)
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                if (!IsDetail)
                {
                    ExpenseOverview expenseOverview = ResultsCache.GetObject(cachePolicy, ExpenseOverview.CacheKey) as ExpenseOverview;
                    expenseOverview.LoadCategoryAccounts(DataAccess.ConnectionString, searchCriteria, Session.SessionID, categoryID);
                }
                else
                {
                    ExpenseDetails expenseDetails = ResultsCache.GetObject(cachePolicy, ExpenseDetails.CacheKey) as ExpenseDetails;
                    expenseDetails.LoadCategoryAccounts(DataAccess.ConnectionString, searchCriteria, Session.SessionID, categoryID, FundNumber);
                }
                filteredAccountTotals = accountsTotal.Select(String.Format("CategoryID = {0}", categoryID));
            }
            DataRow[] filteredActiveAccounts = activeAccounts.Select(String.Format("CategoryID = {0}", categoryID));
            if (filteredActiveAccounts.Length == 0)
            {
                foreach (DataRow filteredAccountTotal in filteredAccountTotals)
                {
                    DataRow accountRow = activeAccounts.NewRow();
                    accountRow[AgreementConstants.CategoryIDColName] = filteredAccountTotal[AgreementConstants.CategoryIDColName];
                    accountRow[AgreementConstants.SortOrderColName] = filteredAccountTotal[AgreementConstants.SortOrderColName];
                    int accountID = (int) filteredAccountTotal[AgreementConstants.AccountIDColName];
//					if (forDownload)
//						accountRow[ExpenseConstants.AccountColumnName] = (string)filteredAccountTotal[ExpenseConstants.AccountNumberColumnName];
//					else
                    accountRow[ExpenseConstants.CategoryColumnName] = filteredAccountTotal[ExpenseConstants.AccountNumberColumnName];
                    accountRow[ExpenseConstants.TotalExpenseAmountColumnName] = filteredAccountTotal[ExpenseConstants.ExpenseAmountColumnName];
                    accountRow[AgreementConstants.AccountIDColName] = accountID;
                    DataRowCollection fundsPerMonthCollection = activeData.Tables[ExpenseConstants.FundsPerMonthTableName].Rows;
                    foreach (DataRow fundRow in fundsPerMonthCollection)
                    {
                        string expenseMonth = (string) fundRow[ExpenseConstants.ExpenseMonthColumnName];
                        DataRow[] accountRows = accounts.Select(string.Format("{0}={1} AND {2}='{3}' AND {4}='{5}'",
                            AgreementConstants.CategoryIDColName, categoryID, AgreementConstants.AccountIDColName, accountID,
                            ExpenseConstants.ExpenseMonthColumnName, expenseMonth));

                        if (accountRows.Length > 0)
                        {
                            accountRow[expenseMonth] = (accountRows[FirstRowIndex][ExpenseConstants.ExpenseAmountColumnName] == DBNull.Value) ? 0 : accountRows[FirstRowIndex][ExpenseConstants.ExpenseAmountColumnName];
                        }
                        else
                        {
                            accountRow[expenseMonth] = 0;
                        }
                    }
                    activeAccounts.Rows.Add(accountRow);
                }
            }
        }

        /// <summary>
        /// Constructs the active data tables and loads them with data. The data
        /// on the active tables is subset of data taken from the ExpenseOverview/Details
        /// instance. The subset is the data required for the current page. The data in the
        /// tables is row wise, which is transformed column wise at the run time based on the
        /// current page index. Only the data pertinent for the current set of expense months
        /// on this page is loaded from the original data container and loaded in repective tables
        /// in the ActiveData dataset, which is then used for binding data to data grid.
        /// </summary>
        private void LoadActiveDataTables()
        {
            ConstructActiveDataTables();

            DataSet activeData = ActiveData;

            DataTable activeCategories = activeData.Tables[Constants.AgreementsConstants.CategoryTableName];

            DataSet dataContainer = ExpenseDataContainer;
            DataTable category = dataContainer.Tables[Constants.AgreementsConstants.CategoryTableName];

            DataRowCollection categoryCollection = dataContainer.Tables[ExpenseConstants.CategoryTotalTableName].Rows;
            DataRowCollection fundsPerMonthCollection = activeData.Tables[ExpenseConstants.FundsPerMonthTableName].Rows;

            foreach (DataRow row in categoryCollection)
            {
                DataRow categoryRow = activeCategories.NewRow();
                int categoryID = (int) row[AgreementConstants.CategoryIDColName];
                int sortOrder = (int) row[AgreementConstants.SortOrderColName];
                categoryRow[AgreementConstants.CategoryIDColName] = categoryID;
                categoryRow[AgreementConstants.SortOrderColName] = sortOrder;
                string categoryName = (string) row[ExpenseConstants.CategoryColumnName];
                categoryRow[ExpenseConstants.CategoryColumnName] = categoryName;
                categoryRow[ExpenseConstants.TotalExpenseAmountColumnName] = row[ExpenseConstants.ExpenseAmountColumnName];
                categoryRow[ExpenseConstants.AccountIDColumnName] = 0;

                foreach (DataRow fundRow in fundsPerMonthCollection)
                {
                    string expenseMonth = (string) fundRow[ExpenseConstants.ExpenseMonthColumnName];

                    DataRow[] filteredCategoryRows = category.Select(string.Format("{0}={1} AND {2}='{3}'",
                        AgreementConstants.CategoryIDColName, categoryID, ExpenseConstants.ExpenseMonthColumnName, expenseMonth));
                    if (filteredCategoryRows.Length > 0)
                    {
                        categoryRow[expenseMonth] = filteredCategoryRows[FirstRowIndex][ExpenseConstants.ExpenseAmountColumnName];
                    }
                }
                activeCategories.Rows.Add(categoryRow);
            }

            DataTable directCost = dataContainer.Tables[Constants.AgreementsConstants.DirectCostsTableName];
            DataTable activeDirectCost = directCost.Clone();
            activeData.Tables.Add(activeDirectCost);

            DataTable indirectCost = dataContainer.Tables[Constants.AgreementsConstants.IndirectCostsTableName];
            DataTable activeIndirectCost = indirectCost.Clone();
            activeData.Tables.Add(activeIndirectCost);

            DataTable totalCost = dataContainer.Tables[Constants.AgreementsConstants.TotalCostsTableName];
            DataTable activeTotalCost = totalCost.Clone();
            activeData.Tables.Add(activeTotalCost);

            DataTable revenue = dataContainer.Tables[Constants.AgreementsConstants.RevenueTableName];
            DataTable activeRevenue = revenue.Clone();
            activeData.Tables.Add(activeRevenue);

            DataTable cashBalance = dataContainer.Tables[Constants.AgreementsConstants.CashBalanceTableName];
            DataTable activeCashBalance = cashBalance.Clone();
            activeData.Tables.Add(activeCashBalance);

            foreach (DataRow fundRow in fundsPerMonthCollection)
            {
                string filter = string.Format("{0}='{1}'", ExpenseConstants.ExpenseMonthColumnName,
                    fundRow[ExpenseConstants.ExpenseMonthColumnName]);

                DataRow[] directCostsRows = directCost.Select(filter);
                if (directCostsRows.Length > 0)
                {
                    activeDirectCost.ImportRow(directCostsRows[FirstRowIndex]);
                }

                DataRow[] indirectCostsRows = indirectCost.Select(filter);
                if (indirectCostsRows.Length > 0)
                {
                    activeIndirectCost.ImportRow(indirectCostsRows[FirstRowIndex]);
                }

                DataRow[] totalCostRows = totalCost.Select(filter);
                if (totalCostRows.Length > 0)
                {
                    activeTotalCost.ImportRow(totalCostRows[FirstRowIndex]);
                }

                DataRow[] revenueRows = revenue.Select(filter);
                if (revenueRows.Length > 0)
                {
                    activeRevenue.ImportRow(revenueRows[FirstRowIndex]);
                }

                DataRow[] cashBalanceRows = cashBalance.Select(filter);
                if (cashBalanceRows.Length > 0)
                {
                    activeCashBalance.ImportRow(cashBalanceRows[FirstRowIndex]);
                }
            }

            dataGrid.ShowFooter = activeCategories.Rows.Count != 1;
        }

        /// <summary>
        /// Constructs category, accounts and fundspermonth table. Apart from the fixed
        /// columns, columns are added dynamically to these tables based on the value
        /// of current page index. The names of columns added dynamically on the category 
        /// and accounts tables are given the name of the expense month on funds per month table.
        /// Naming the column as expense month, makes it easy to populate data in the active category 
        /// and account tables from the original table from the ExpenseOverview/Details instance. Since
        /// the navigation on this page is on columns, the "start row" and "end row" is calculated
        /// using the CurrentPageIndex, MaxExpenseMonthColumns on a page and the row count
        /// of the fundsPerMonth table. While calculating both it has to be kept in mind that the
        /// highest value of CurrentPageIndex can be '0'. The user can navigate back to different set
        /// of expense months wherein the page index is subtracted from the current index. The number
        /// of expense month columns to be displayed on the current page is determned using the startRow
        /// and endRow. The columns to be displayed on the first load (CurrentPageIndex=0) are the latest
        /// expense month plus 11 more months from the latest expense month. This method also manages the
        /// display of navigate next and navigate previous buttons based on the values of rowCount, start 
        /// row and endrow
        /// </summary>
        private void ConstructActiveDataTables()
        {
            DataTable categories = new DataTable(Constants.AgreementsConstants.CategoryTableName);
            categories.Columns.Add(AgreementConstants.CategoryIDColName, typeof (SqlInt32));
            categories.Columns.Add(AgreementConstants.SortOrderColName, typeof (SqlInt32));
            categories.Columns.Add(ExpenseConstants.CategoryColumnName, typeof (SqlString));
            categories.Columns.Add(AgreementConstants.AccountIDColName, typeof (SqlInt32));
            categories.Columns.Add(ExpenseConstants.TotalExpenseAmountColumnName, typeof (SqlDecimal));

            DataTable accounts = new DataTable(Constants.AgreementsConstants.AccountsTableName);
            accounts.Columns.Add(AgreementConstants.CategoryIDColName, typeof (SqlInt32));
            accounts.Columns.Add(AgreementConstants.SortOrderColName, typeof (SqlInt32));
            accounts.Columns.Add(ExpenseConstants.CategoryColumnName, typeof (SqlString));
            accounts.Columns.Add(AgreementConstants.AccountIDColName, typeof (SqlInt32));
            accounts.Columns.Add(ExpenseConstants.TotalExpenseAmountColumnName, typeof (SqlDecimal));

            DataTable fundsPerMonth = ExpenseDataContainer.Tables[ExpenseConstants.FundsPerMonthTableName];

            int rowCount = fundsPerMonth.Rows.Count;

            pager.RecordCount = rowCount;
            pager.PageCount = (pager.RecordCount/MaxExpenseMonthColumns) +
                (((pager.RecordCount%MaxExpenseMonthColumns) == 0) ? 0 : 1);

            int currentPageIndex = CurrentPageIndex;
            int startRow = currentPageIndex*MaxExpenseMonthColumns;
            int endRow = Math.Min(startRow + MaxExpenseMonthColumns, rowCount);

            ExpenseMonthColumnCount = endRow - startRow;

            pager.FirstRecord = startRow + 1; // Pager is 1-based.
            pager.LastRecord = endRow;
            pager.CurrentPage = currentPageIndex + 1; // Pager is 1-based.

            pager.EnableFirstPage = pager.EnablePreviousPage = (currentPageIndex != 0);
            pager.EnableLastPage = pager.EnableNextPage = (currentPageIndex != (pager.PageCount - 1));

            DataTable activeFundsPerMonth = fundsPerMonth.Clone();
            for (int index = startRow; index < endRow; index++)
            {
                DataRow currentRow = fundsPerMonth.Rows[index];
                string expenseMonth = currentRow[ExpenseConstants.ExpenseMonthColumnName].ToString();
                categories.Columns.Add(expenseMonth, typeof (SqlDecimal));
                accounts.Columns.Add(expenseMonth, typeof (SqlDecimal));
                activeFundsPerMonth.ImportRow(currentRow);
            }

            DataSet activeData = new DataSet();
            activeData.Tables.Add(activeFundsPerMonth);
            activeData.Tables.Add(categories);
            activeData.Tables.Add(accounts);
            ActiveData = activeData;
        }

        /// <summary>
        /// This method adds the expense month columns to the datagrid based on the
        /// number of rows in fundsPerMonth table from the active dataset for the page.
        /// Before adding the columns the existing expense month columns are removed
        /// from the datagrid. The grid has some fixed columns, the expense month
        /// columns are added dynamically. Each column being added has header, footer and
        /// item template which is contructed usign the templates from the expense templates
        /// class.
        /// </summary>
        private void AddExpenseMonthColumns()
        {
            int columnCount = dataGrid.Columns.Count;
            int expandingGridFixedColumnsCount = FixedColumnsCount + 1;
            if (columnCount > expandingGridFixedColumnsCount)
            {
                for (int i = 0, countToRemove = columnCount - expandingGridFixedColumnsCount; i < countToRemove; ++i)
                {
                    dataGrid.Columns.RemoveAt(FixedColumnsCount);
                }
            }

            DataSet activeData = ActiveData;
            if (activeData != null)
            {
                DataRowCollection rows = activeData.Tables[ExpenseConstants.FundsPerMonthTableName].Rows;
                int index = FixedColumnsCount;
                foreach (DataRow row in rows)
                {
                    TemplateColumn templateColumn = new TemplateColumn();

                    string expenseMonth = (string) row[ExpenseConstants.ExpenseMonthColumnName];
                    templateColumn.HeaderTemplate = new ExpenseTemplates.HeaderTemplate(IsDetail, expenseMonth,
                        row[ExpenseConstants.NoOfFundsColumnName].ToString());
                    templateColumn.ItemTemplate = new ExpenseTemplates.LinkButtonTemplate(expenseMonth, expenseMonth);
                    templateColumn.FooterTemplate = new ExpenseTemplates.FooterTemplate(pageCachePolicy, index - FixedColumnsCount);

                    dataGrid.Columns.AddAt(index, templateColumn);
                    ++index;
                }
            }
        }

        /// <summary>
        /// Configure a new lable and add it to the specifed control collection.
        /// </summary>
        /// <param name="controlCollection">Control collection to which label has to be added</param>
        private void ConfigureNewLabel(ControlCollection controlCollection)
        {
            Label label = new Label();
            label.Text = ((LinkButton) controlCollection[0]).Text;
            controlCollection.Clear();
            controlCollection.Add(label);
        }

        /// <summary>
        /// This method supports formatting and style setting for labels,
        /// textboxes and table cells displaying currency values. It determines the
        /// type of control and gets the value in the dataitem. Based on the value
        /// of the dataitem, cssclass and text property of the control is set.
        /// </summary>
        /// <param name="control">control to be formatted</param>
        /// <param name="dataItem">data to be displayed in the control</param>
        private void FormatCurrencyValue(object control, object dataItem)
        {
            decimal itemValue = Convert.ToDecimal((dataItem != DBNull.Value) ? dataItem.ToString() : DefaultAmount); //Math.Round(Convert.ToDecimal((dataItem != DBNull.Value) ? dataItem.ToString() : DefaultAmount), 1);
            if (control is Label)
            {
                Label item = (Label) control;
                item.CssClass = (itemValue < 0) ? AgreementConstants.ExpandedGridDeficitStyle : AgreementConstants.ExpandedGridCurrencyStyle;
                item.Text = Helper.ProcessDecimals(itemValue); //itemValue.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
            }
            else if (control is LinkButton)
            {
                LinkButton item = (LinkButton) control;
                item.CssClass = (itemValue < 0) ? AgreementConstants.ExpandedGridDeficitStyle : AgreementConstants.ExpandedGridCurrencyStyle;
                item.Text = Helper.ProcessDecimals(itemValue); //itemValue.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
            }
            else if (control is TableCell)
            {
                TableCell item = (TableCell) control;
                item.CssClass = (itemValue < 0) ? AgreementConstants.DeficitStyle : AgreementConstants.CurrencyStyle;
                item.Text = Helper.ProcessDecimals(itemValue); //itemValue.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
            }
        }

        /// <summary>
        /// Creates a table containing labels which display the
        /// captions for direct costs, direct cost balance, indirect costs,
        /// total costs, revenue and cash balance rows
        /// </summary>
        /// <returns>WebControls.Table with footer captions</returns>
        private Table GetCategoryFooterTable()
        {
            Table categoryFooterTable = new Table();

            Label direcost = new Label();
            direcost.Text = "<nobr>Direct Costs</nobr>";
            AddNewRowWithLabel(categoryFooterTable, direcost);

            Label indirectCost = new Label();
            indirectCost.Text = "<nobr>Indirect Costs</nobr>";
            AddNewRowWithLabel(categoryFooterTable, indirectCost);

            Label totalCost = new Label();
            totalCost.Text = "<nobr>Total Costs</nobr>";
            AddNewRowWithLabel(categoryFooterTable, totalCost);

            //            Label directCostBalance = new Label();
            //            directCostBalance.Text = "<nobr>Direct Cost Balance</nobr>";
            //            AddNewRowWithLabel(categoryFooterTable, directCostBalance);

            Label revenue = new Label();
            revenue.Text = "<nobr>Revenue</nobr>";
            AddNewRowWithLabel(categoryFooterTable, revenue);

            Label cashBalance = new Label();
            cashBalance.Text = "<nobr>Cash Balance</nobr>";
            AddNewRowWithLabel(categoryFooterTable, cashBalance);

            return categoryFooterTable;
        }

        /// <summary>
        /// Creates a table containing the controls displaying the totals
        /// for direct cost, indirect cost, direct cost balance, total costs,
        /// revenue and cash balance in the footer of the Totals column.
        /// </summary>
        /// <returns>WebControls.Table table containing totals for foooter</returns>
        private Table GetTotalsFooterTable()
        {
            Table totalTable = new Table();
            totalTable.CssClass = "FooterTotalTable";

            DataSet dataContainer = ExpenseDataContainer;
            int footerTablesTotalRowIndex = 0;

            if (dataContainer.Tables[ExpenseConstants.FooterTotalsTableName].Rows.Count != 0)
            {
                Label directCost = new Label();
                FormatCurrencyValue(directCost, dataContainer.Tables[ExpenseConstants.FooterTotalsTableName].
                    Rows[footerTablesTotalRowIndex][ExpenseConstants.DirectCostsTotalColumnName]);
                AddNewRowWithLabel(totalTable, directCost);

                Label indirectCost = new Label();
                FormatCurrencyValue(indirectCost, dataContainer.Tables[ExpenseConstants.FooterTotalsTableName].
                    Rows[footerTablesTotalRowIndex][ExpenseConstants.IndirectCostsTotalColumnName]);
                AddNewRowWithLabel(totalTable, indirectCost);

                Label totalCostLabel = new Label();
                object totalCostItem = dataContainer.Tables[ExpenseConstants.FooterTotalsTableName].
                    Rows[footerTablesTotalRowIndex][ExpenseConstants.TotalCostsTotalColumnName];

                FormatCurrencyValue(totalCostLabel, totalCostItem);
                AddNewRowWithLabel(totalTable, totalCostLabel);

                //                Label directCostBalance = new Label();			
                //                FormatCurrencyValue(directCostBalance, dataContainer.Tables[ExpenseConstants.FooterTotalsTableName].
                //                    Rows[footerTablesTotalRowIndex][ExpenseConstants.DirectCostBalanceTotalColumnName]);
                //                AddNewRowWithLabel(totalTable, directCostBalance);

                Label revenueLabel = new Label();
                object revenueItem = dataContainer.Tables[ExpenseConstants.FooterTotalsTableName].
                    Rows[footerTablesTotalRowIndex][ExpenseConstants.RevenueTotalColumnName];

                FormatCurrencyValue(revenueLabel, revenueItem);
                AddNewRowWithLabel(totalTable, revenueLabel);

                //cashBalance is the revenue - totalCost value
                Label cashBalance = new Label();
                decimal cashBalanceValue = 0;
                DataTable cashbalances = dataContainer.Tables[Constants.AgreementsConstants.CashBalanceTableName];
                if (cashbalances.Rows.Count > 0)
                {
                    cashBalanceValue = Convert.ToDecimal(cashbalances.Rows[cashbalances.Rows.Count - 1]["ExpenseAmount"]);
                }

                cashBalance.CssClass = (cashBalanceValue < 0) ? AgreementConstants.ExpandedGridDeficitStyle : AgreementConstants.ExpandedGridCurrencyStyle;
                FormatCurrencyValue(cashBalance, cashBalanceValue);
                AddNewRowWithLabel(totalTable, cashBalance);
            }
            return totalTable;
        }

        /// <summary>
        /// Adds a new row to the specifed table and adds the sepcified
        /// label to a cell in the new row.
        /// </summary>
        /// <param name="table">table to which the row has to be added</param>
        /// <param name="label">label which has to be added to the new row in the table</param>
        private void AddNewRowWithLabel(Table table, Label label)
        {
            label.Font.Bold = true;
            TableRow row = new TableRow();
            table.Rows.Add(row);
            TableCell cell = new TableCell();
            row.Cells.Add(cell);
            cell.Controls.Add(label);
        }

        /// <summary>
        /// Adds refresh dates currently visible on the page to the search criteria string
        /// to be passed down to reports. The criteria does not persist to the SearchCriteria
        /// object.
        /// </summary>
        /// <param name="searchCriteria">Object containing search criteria.</param>
        /// <returns>A string representation of search criteria. </returns>
        private string AddRefreshDatesToCriteria(SearchCriteria searchCriteria)
        {
            StringBuilder criteria = new StringBuilder(searchCriteria.ToString(";"));
            if (refreshDates.SalaryAsOfDateVisible)
            {
                criteria.AppendFormat("Last Salary Post|{0};", refreshDates.SalaryAsOfDate.ToShortDateString());
            }
            if (refreshDates.GLAsOfDateVisible)
            {
                criteria.AppendFormat("Last GL Post|{0};", refreshDates.GLPostAsOfDate.ToShortDateString());
            }
            if (refreshDates.POAPAsOfDateVisible)
            {
                criteria.AppendFormat("Last PO/AP Post|{0};", refreshDates.POAPAsOfDate.ToShortDateString());
            }
            return criteria.ToString();
        }

        /// <summary>
        /// Uncaches all objects with data for this page. Also syncs up the search criteria
        /// number and the one stored on the page cache to ensure database does not inadvertently
        /// get hit when accessing page's BO properties due to version number changes.
        /// </summary>
        private void PurgeCache()
        {
            SearchCriteriaVersion = ((CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString()).Version;
            if (IsDetail)
            {
                ExpenseDetails.Purge();
                cachePolicy.UnCache(ExpenseDetails.CacheKey);
            }
            else
            {
                ExpenseOverview.Purge();
                cachePolicy.UnCache(ExpenseOverview.CacheKey);
            }
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Handler for the event raised when the page is being initialized.
        /// Retrieve the cache policy in force. Adds columns to the grid if the
        /// page is post back. This is done here so that the click on cells in
        /// respective columns raises item command event, which can be handled
        /// by the code behind.
        /// </summary>
        /// <param name="e">Argument associated with the event</param>
        protected override void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
            viewStateCachePolicy = new PHSRAG.Insight21.Policy.ViewStateCachePolicy(this.ViewState);

            OverviewSearch overviewSearch = (OverviewSearch) commonSearch.EmbeddedSearchControl;
            overviewSearch.CategoryChanged += new CommandEventHandler(OnCategoryChanged);

            if (IsPostBack)
            {
                AddExpenseMonthColumns();
            }
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }

        #endregion
    }
}